package game;

/**
 * 老鼠出迷宫
 * 思路：
 * 1. 先构建迷宫（1为障碍物，0为路）✅
 * 2. 老鼠起点是（1，1），迷宫终点是（6,5）
 * 3. 老鼠在起点执行找路策略 findWay 返回为true说明找到了出迷宫的路
 */
public class MouseOutOfMaze {
    public static void main(String[] args) {
        MouseOutOfMaze mouseOutOfMaze = new MouseOutOfMaze();
        //构建迷宫
        char[][] map = mouseOutOfMaze.buildMaze();
        mouseOutOfMaze.printMaze(map, "构建好的迷宫");
        mouseOutOfMaze.findWay(map, 1, 1);
        mouseOutOfMaze.printMaze(map, "老鼠找路后的迷宫");
    }

    /**
     * 构建迷宫方法
     */
    public char[][] buildMaze() {
        //构建迷宫
        char[][] map = new char[8][7];
        //初始化所有的为空心方块
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[i].length; j++) {
                map[i][j] = '⬜';
            }
        }
        //最上面一行和最下面一行都是1
        for (int j = 0; j <= 6; j++) {
            map[0][j] = '⬛';
            map[7][j] = '⬛';
        }
        //最左边一列和最右边一列都是1
        for (int i = 0; i <= 7; i++) {
            map[i][0] = '⬛';
            map[i][6] = '⬛';
        }
        //障碍物设置
        map[3][1] = '⬛';
        map[3][2] = '⬛';
        map[4][3] = '⬛';
        map[2][2] = '⬛';
        map[3][4] = '⬛';
        map[5][5] = '⬛';
//        map[6][4] = 1;
        return map;
    }

    /**
     * 迷宫打印
     */
    public void printMaze(char[][] map, String mes) {
        System.out.println("\n====" + mes + "====");
        //打印一下构建好的迷宫  int[8][7]
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[i].length; j++) {
                System.out.print(map[i][j] + "\t");
            }
            System.out.println();
        }

    }

    /**
     * 设置老鼠的找路策略
     * 思路：
     * 1. 输入老鼠的起点
     * 2. 0为没有探索过的路段,1为障碍物,2为正在探测是否能找到终点路段中的点，3为探测过不能走的路段
     *    符号则：⬛为障碍物/墙 ，⬜为没有探索过的路，✅为探索中的路，❌为探索过走不通终点的路
     *    对于3，肯定是不能折返的，折返某个方向发现某个点是之前探测过的，说明这个方向为false，应该探索其他方向
     *    四个方向都为障碍物/探测中的点，说明这个方向这个点不通，标记为3
     * 3. 找路策略，右->下->左->上
     * 整体思路总结：
     *     findWay就是我们的探测仪，探测仪探测到终点，返回true，如果四个方向都没探测到终点，返回false
     *     对于探索中的点,临时标记为✅，我们按照一定的找路策略去探索没有探索过的点，如果四个方向都探测不到，则返回false
     *
     * @param map 迷宫本身
     * @param i   找路的坐标，走到的点，执行探测路的位置
     * @param j
     * @return
     */
    public boolean findWay(char[][] map, int i, int j) {
        //结束条件，探测过程中，探测仪成功探测到终点!
        if (map[6][5] == '✅') {
            return true;//成功找到一条路
        } else {
            //还没探测到终点，继续探测
            //只探测没有探测过的点
            if (map[i][j] == '⬜') {
                map[i][j] = '✅';//开启探测标识，表明当前点正在探测中
                //找路策略，右->下->左->上
                //下
                if (findWay(map, i + 1, j)) {
                    return true;
                }
                //右
                if (findWay(map, i, j + 1)) {
                    return true;
                }

                //左
                if (findWay(map, i, j - 1)) {
                    return true;
                }
                //上
                if (findWay(map, i - 1, j)) {
                    return true;
                }
                //如果当前位置的上下左右的走不了，说明当前位置是走不通
                // 的，最终也无法找到路，标记为❌，当前点已经探测完
                map[i][j] = '❌';
                return false;//已经堵死了，整条路都终止了
                //当前点返回false，前置探测点可以继续探索其他方向
            } else {
                //如果当前点已经探测过，无需重复探测，
                // 返回false，前置探测点继续探索其他方向
                return false;
            }
        }
    }

}
